﻿using CMS.Infos;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;

namespace CMS
{
    public class CourseDisplay : Control
    {


        #region 内部数据存储
        private Rectangle _FramRect;
        private Course[] _Courses = null;
        #endregion

        #region 对外接口
        /// <summary>
        /// 当课程选择状态被改变时,触发此事件
        /// </summary>
        public event EventHandler SelectCourseChanged;

        /// <summary>
        /// 读取当前鼠标所选择的位置的课程信息
        /// </summary>
        public Point SelectPoint { get; private set; } = Point.Empty;

        /// <summary>
        /// 读取或设置要显示的课程信息
        /// </summary>
        public Course[] Courses { get => _Courses; set { _Courses = value; Invalidate(); SelectCourseChanged?.Invoke(this, EventArgs.Empty); } }

        /// <summary>
        /// 读取当前选择的位置的课程信息
        /// </summary>
        public Course[] SelectCourses
        {
            get
            {
                if (SelectPoint.IsEmpty || Courses == null)
                {
                    return new Course[0];
                }

                int time = 1 << (SelectPoint.Y - 1);
                return (from c in _Courses where c.Week == SelectPoint.X && (c.ClassTimeRaw & time) != 0 select c).ToArray();
            }
        }
        #endregion



        public CourseDisplay()
        {
            DoubleBuffered = true;
            BackColor = Color.White;
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            int x = e.X / (Width / 8);
            int y = e.Y / (Height / 15);
            SelectPoint = (x == 0 || y == 0) ? Point.Empty : new Point(x, y);
            Invalidate();
            SelectCourseChanged?.Invoke(this, EventArgs.Empty);
            base.OnMouseClick(e);
        }


        #region 参数更新

        protected override void OnSizeChanged(EventArgs e)
        {
            if (Height / 15 != 1 || Width / 8 != 1)
            {
                Size = new Size(Width - Width % 8 + 1, Height - Height % 15 + 1);
            }
            base.OnSizeChanged(e);
            _FramRect.Width = Width - 1;
            _FramRect.Height = Height - 1;
        }
        #endregion

        #region 绘制相关
        private readonly Pen RectPen = new Pen(Color.LightGray);
        private readonly Pen TitlePen = new Pen(Color.Black) { DashStyle = DashStyle.Dot };
        private readonly Pen LightPen = new Pen(Color.LightGray);
        private readonly Font TitleFont = new Font("微软雅黑", 15, GraphicsUnit.Pixel);
        private readonly Brush TitleBrush = new SolidBrush(Color.Black);
        private readonly StringFormat TitleForatmat = new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
        private readonly Font CourseFont = new Font("微软雅黑", 8);
        private readonly StringFormat CourseFormat = new StringFormat() { Alignment = StringAlignment.Center };

        #region 常量
        public static readonly string[] Weeks = new string[]
        {
            "星期一",
            "星期二",
            "星期三",
            "星期四",
            "星期五",
            "星期六",
            "星期日"
        };

        private readonly Brush[] MyBrushes = new Brush[] {
            //new SolidBrush(ColorTranslator.FromHtml("#bdbdbd")),
            new SolidBrush(ColorTranslator.FromHtml("#ff5757")),
            new SolidBrush(ColorTranslator.FromHtml("#ff80bf")),
            new SolidBrush(ColorTranslator.FromHtml("#be77ff")),
            new SolidBrush(ColorTranslator.FromHtml("#a9a9ff")),
            new SolidBrush(ColorTranslator.FromHtml("#85c2ff")),
            new SolidBrush(ColorTranslator.FromHtml("#33bebe")),
            new SolidBrush(ColorTranslator.FromHtml("#34c379")),
            new SolidBrush(ColorTranslator.FromHtml("#8fcc33")),
            new SolidBrush(ColorTranslator.FromHtml("#ffe35d")),
            new SolidBrush(ColorTranslator.FromHtml("#ff9933"))
        };
        #endregion

        #region 工具函数
        /// <summary>
        /// 获取圆角矩形
        /// </summary>
        /// <param name="x">开始绘制的x坐标</param>
        /// <param name="y">开始绘制的y坐标</param>
        /// <param name="w">圆矩形的宽</param>
        /// <param name="h">圆矩形的高</param>
        /// <param name="r">圆矩形的圆角的半径</param>
        /// <returns></returns>
        private static GraphicsPath GetRoundRect(int x, int y, int w, int h, int r)
        {
            GraphicsPath path = new GraphicsPath();

            int r2 = 2 * r;
            path.AddLine(x + r, y, x + w - r, y);
            //path.AddArc(x + w - r2, y, r2, r2, 270, 90);
            path.AddLine(x + w, y + r, x + w, y + h - r);
            //path.AddArc(x + w - r2, y + h - r2, r2, r2, 0, 90);
            path.AddLine(x + w - r, y + h, x + r, y + h);
            //path.AddArc(x, y + h - r2, r2, r2, 90, 90);
            path.AddLine(x, y + h - r, x, y + r);
            //path.AddArc(x, y, r2, r2, 180, 90);

            path.CloseFigure();
            //path.AddRectangle(new Rectangle(x, y, w, h));
            return path;
        }

        /// <summary>
        /// 记录下一个画刷的序号
        /// </summary>
        private int _ColorIndex = 0;

        /// <summary>
        /// 获取下一个画刷
        /// </summary>
        /// <returns></returns>
        private Brush NextBrush()
        {
            return MyBrushes[_ColorIndex++ % MyBrushes.Length];
        }

        private void ResetBrush()
        {
            _ColorIndex = 0;
        }
        #endregion

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.PageUnit = GraphicsUnit.Pixel;
            int right = _FramRect.Width - 1;
            int bottom = _FramRect.Bottom - 1;

            int ph = Height / 15;
            int pw = Width / 8;

            g.DrawRectangle(RectPen, _FramRect);
            g.DrawLine(RectPen, 1, ph, right, ph);
            g.DrawLine(RectPen, pw, 1, pw, bottom);

            int tmp = ph * 2;
            for (int i = 1; i < 14; i++)
            {
                g.DrawLine(RectPen, 1, tmp, pw, tmp);
                g.DrawLine(LightPen, pw, tmp, right, tmp);

                tmp += ph;
            }
            for (int i = 1; i <= 14; i++)
            {
                g.DrawString($"第{i}节", TitleFont, TitleBrush, new RectangleF(0, ph * i, pw, ph), TitleForatmat);
            }

            tmp = pw * 2;
            for (int i = 1; i < 7; i++)
            {
                g.DrawLine(RectPen, tmp, 1, tmp, ph);
                g.DrawLine(LightPen, tmp, ph, tmp, bottom);
                tmp += pw;
            }
            for (int i = 0; i < 7; i++)
            {
                g.DrawString(Weeks[i], TitleFont, TitleBrush, new RectangleF(pw * (i + 1), 0, pw, ph), TitleForatmat);
            }

            if (_Courses != null)
            {
                const int margin = 5;
                int flag = 1 << (SelectPoint.Y - 1);
                ResetBrush();
                foreach (Course course in _Courses)
                {
                    Rectangle rect = new Rectangle(course.Week * pw +1, course.StartTime * ph + 1, pw - 2, course.TimeSpan * ph - 2);
                    GraphicsPath path = GetRoundRect(rect.X, rect.Y, rect.Width, rect.Height, 5);

                    g.FillPath(NextBrush(), path);
                    if (!SelectPoint.IsEmpty && course.Week == SelectPoint.X && (flag & course.ClassTimeRaw) != 0)
                    {
                       // GraphicsPath path2 = GetRoundRect(rect.X, rect.Y , rect.Width-1 , rect.Height-1 , 5);
                        Pen SelectedPen = new Pen(Color.Gray,2);
                        path.Widen(SelectedPen);
                        g.DrawPath(SelectedPen, path);
                    }
                    rect.Offset(margin, margin);
                    rect.Width -= 2 * margin;
                    rect.Height -= 2 * margin;
                    g.DrawString(course.Name, CourseFont, Brushes.White, rect, CourseFormat);
                }
            }
        }

        #endregion
    }
}
